﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using Pixysoft.Framework.Noebe.Consistency;
using System.Data;
using Pixysoft.Framework.Verifications;

namespace Pixysoft.Framework.Noebe.Orm
{
    /// <summary>
    /// 使用consistency，对象会记录groupcode
    /// </summary>
    class OrmConsistency : Pixysoft.Framework.Noebe.Orm.IOrmConsistency
    {
        public void Deploy<T>()
        {
            Deploy<T>(false);
        }

        public void Deploy<T>(bool forceMode)
        {
            ConsistencyTables tblist = new ConsistencyTables();

            string objname = ReflectHelper.GetInterfaceTypeName(typeof(T));

            string tbname = MappingHelper.GetTableName(objname);

            ConstructConsistencyTables(tblist, typeof(T));

            foreach (string stbname in tblist.Tblist)
            {
                CstNoebeManagerAdapter.Instances[StringHelper.global_framework_id].DeployData(stbname,
                    MappingHelper.GetSysIDName(), false, forceMode);
            }

            foreach (string stbname in tblist.Linklist)
            {
                CstNoebeManagerAdapter.Instances[StringHelper.global_framework_id].DeployData(stbname,
                    MappingHelper.GetSysIDName(), false, forceMode);
            }
        }

        public List<ConsistencySetting> DeployToFile<T>()
        {
            return DeployToFile<T>(false);
        }

        public List<ConsistencySetting> DeployToFile<T>(bool forceMode)
        {
            List<ConsistencySetting> list = new List<ConsistencySetting>();

            ConsistencyTables tblist = new ConsistencyTables();

            string objname = ReflectHelper.GetInterfaceTypeName(typeof(T));

            string tbname = MappingHelper.GetTableName(objname);

            ConstructConsistencyTables(tblist, typeof(T));

            foreach (string stbname in tblist.Tblist)
            {
                ConsistencySetting config = new ConsistencySetting();

                config.IsAutoPk = false;
                config.IsForceMode = forceMode;
                config.MirrorName = stbname;
                config.TableName = stbname;
                config.PkColName = MappingHelper.GetSysIDName();

                list.Add(config);
            }

            foreach (string stbname in tblist.Linklist)
            {
                ConsistencySetting config = new ConsistencySetting();

                config.IsAutoPk = false;
                config.IsForceMode = forceMode;
                config.MirrorName = stbname;
                config.TableName = stbname;
                config.PkColName = MappingHelper.GetSysIDName();

                list.Add(config);
            }

            return list;
        }


        public virtual bool Download<T>()
        {
            string objname = ReflectHelper.GetInterfaceTypeName(typeof(T));

            string tbname = MappingHelper.GetTableName(objname);

            ConsistencyTables tblist = new ConsistencyTables();

            ConstructConsistencyTables(tblist, typeof(T));

            foreach (string dtbname in tblist.Tblist)
            {
                ConsistencyResult dresult = CstNoebeManagerAdapter.Instances[StringHelper.global_framework_id].Consistency.Download(dtbname);

                //修改本地table的groupcode

                DataTable csttable = dresult.CstTable;

                foreach (DataRow row in csttable.Rows)
                {
                    row[StringHelper.ORM_GROUPCODE] = row["CST$GROUPCODE"];
                }

                DataTable realtb = dresult.Table;

                Pixysoft.Data.TableMapping.Instance.MappingManyToMany(csttable, realtb);

                NoebeCommandHelper.GetNoebeCommand().Update(realtb);

                if (!dresult.Passed)
                    return false;
            }

            foreach (string dtbname in tblist.Linklist)
            {
                CstNoebeManagerAdapter.Instances[StringHelper.global_framework_id].Consistency.Download(dtbname);
            }

            return true;
        }

        public virtual bool DownloadMe<T>()
        {
            ConsistencyTables tblist = new ConsistencyTables();

            string objname = ReflectHelper.GetInterfaceTypeName(typeof(T));

            string tbname = MappingHelper.GetTableName(objname);

            ConstructConsistencyTables(tblist, typeof(T));

            foreach (string dtbname in tblist.Tblist)
            {
                ConsistencyResult dresult = CstNoebeManagerAdapter.
                    Instances[StringHelper.global_framework_id].Consistency.DownloadMe(dtbname);

                if (!dresult.Passed)
                    return false;
            }

            foreach (string dtbname in tblist.Linklist)
            {
                CstNoebeManagerAdapter.Instances[StringHelper.global_framework_id].Consistency.DownloadMe(dtbname);
            }

            return true;
        }

        public virtual bool Upload<T>()
        {
            ConsistencyTables tblist = new ConsistencyTables();

            string objname = ReflectHelper.GetInterfaceTypeName(typeof(T));

            string tbname = MappingHelper.GetTableName(objname);

            ConstructConsistencyTables(tblist, typeof(T));

            foreach (string dtbname in tblist.Tblist)
            {
                ConsistencyUploadResult uresult = CstNoebeManagerAdapter.
                    Instances[StringHelper.global_framework_id].Consistency.Upload(dtbname);

                ConsistencyResult dresult = uresult.DownloadResult;

                if (!dresult.Passed)
                    return false;
            }

            foreach (string dtbname in tblist.Linklist)
            {
                CstNoebeManagerAdapter.Instances[StringHelper.global_framework_id].Consistency.Upload(dtbname);
            }

            return true;
        }

        public virtual bool UploadMe<T>()
        {
            ConsistencyTables tblist = new ConsistencyTables();

            string objname = ReflectHelper.GetInterfaceTypeName(typeof(T));

            string tbname = MappingHelper.GetTableName(objname);

            ConstructConsistencyTables(tblist, typeof(T));

            foreach (string dtbname in tblist.Tblist)
            {
                ConsistencyUploadResult uresult = CstNoebeManagerAdapter.
                    Instances[StringHelper.global_framework_id].Consistency.UploadMe(dtbname);

                ConsistencyResult dresult = uresult.DownloadResult;

                if (!dresult.Passed)
                    return false;
            }

            foreach (string dtbname in tblist.Linklist)
            {
                CstNoebeManagerAdapter.Instances[StringHelper.global_framework_id].Consistency.UploadMe(dtbname);
            }

            return true;
        }


        /// <summary>
        /// 构造相关表列表
        /// </summary>
        /// <param name="tblist"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        protected bool ConstructConsistencyTables(ConsistencyTables tblist, Type type)
        {
            string objName = ReflectHelper.GetInterfaceTypeName(type);

            string tablename = MappingHelper.GetTableName(objName);

            if (tblist.Tblist.Contains(tablename))
                return false;

            tblist.Tblist.Insert(0, tablename);

            foreach (PropertyInfo info in type.GetProperties())
            {
                string fieldname = info.Name.ToUpper();

                Type fieldType = info.PropertyType;

                switch (ReflectHelper.GetOrmTypeByType(fieldType))
                {
                    case DotNetPropertyType.Enum:
                    case DotNetPropertyType.Value:
                    case DotNetPropertyType.BinaryList:
                    case DotNetPropertyType.Binary:
                        {
                            continue;
                        }
                    case DotNetPropertyType.Interface:
                    case DotNetPropertyType.Object:
                        {
                            ConstructConsistencyTables(tblist, fieldType);

                            break;
                        }


                    case DotNetPropertyType.ValueList:
                    case DotNetPropertyType.EnumList:
                    case DotNetPropertyType.ValueArray:
                    case DotNetPropertyType.EnumArray:
                        {
                            string linkTbName = MappingHelper.GetLinkTableName(objName, fieldname);

                            if (tblist.Linklist.Contains(linkTbName))
                                throw new Exception("dulicated tablename for " + linkTbName);
                            else
                                tblist.Linklist.Add(linkTbName);

                            break;
                        }

                    case DotNetPropertyType.ObjectArray:
                    case DotNetPropertyType.InterfaceArray:
                        {
                            ConstructConsistencyTables(tblist, fieldType.GetElementType());

                            string linkTbName = MappingHelper.GetLinkTableName(objName, fieldname);

                            if (tblist.Linklist.Contains(linkTbName))
                                throw new Exception("dulicated tablename for " + linkTbName);
                            else
                                tblist.Linklist.Add(linkTbName);

                            break;
                        }
                    case DotNetPropertyType.InterfaceList:
                    case DotNetPropertyType.ObjectList:
                        {
                            Type[] argsTypes = fieldType.GetGenericArguments();

                            if (argsTypes.Length != 1)
                                throw new Exception("error in generic args");

                            ConstructConsistencyTables(tblist, argsTypes[0]);

                            string linkTbName = MappingHelper.GetLinkTableName(objName, fieldname);

                            if (tblist.Linklist.Contains(linkTbName))
                                throw new Exception("dulicated tablename for " + linkTbName);
                            else
                                tblist.Linklist.Add(linkTbName);

                            break;
                        }

                    default:
                        {
                            continue;
                        }
                }
            }

            return true;
        }

        protected class ConsistencyTables
        {
            List<string> tblist = new List<string>();

            List<string> linklist = new List<string>();

            public List<string> Tblist
            {
                get { return tblist; }
                set { tblist = value; }
            }
            public List<string> Linklist
            {
                get { return linklist; }
                set { linklist = value; }
            }
        }
    }
}
